use syntect::{
    easy::HighlightLines,
    highlighting::{Style, ThemeSet},
    parsing::SyntaxSet,
    util::{as_24_bit_terminal_escaped, LinesWithEndings},
};

use crate::util::property;

pub fn hightlight(content: &str, code_extension: &str) -> String {
    // 主题
    let env = property::Env::init();
    let theme_set = ThemeSet::load_defaults();
    let theme = &theme_set.themes[&env.code_hight_theme];

    let syntex_set = SyntaxSet::load_defaults_newlines();

    let language_syntax = syntex_set.find_syntax_by_extension(code_extension).unwrap();
    let mut highlight_lines = HighlightLines::new(language_syntax, theme);
    let result = LinesWithEndings::from(content)
        .into_iter()
        .map(|line| {
            let ranges: Vec<(Style, &str)> =
                highlight_lines.highlight_line(line, &syntex_set).unwrap();
            let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
            return escaped;
        })
        .collect();
    return result;
}

#[test]
fn highlight_test() {
    let content = r#"
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractPublicKey = exports.recoverPersonalSignature = exports.personalSign = void 0;
const ethereumjs_util_1 = require("ethereumjs-util");
const utils_1 = require("./utils");
/**
 * Create an Ethereum-specific signature for a message.
 *
 * This function is equivalent to the `eth_sign` Ethereum JSON-RPC method as specified in EIP-1417,
 * as well as the MetaMask's `personal_sign` method.
 *
 * @param options - The personal sign options.
 * @param options.privateKey - The key to sign with.
 * @param options.data - The hex data to sign.
 * @returns The '0x'-prefixed hex encoded signature.
 */
function personalSign({ privateKey, data, }) {
    if (utils_1.isNullish(data)) {
        throw new Error('Missing data parameter');
    }
    else if (utils_1.isNullish(privateKey)) {
        throw new Error('Missing privateKey parameter');
    }
    const message = utils_1.legacyToBuffer(data);
    const msgHash = ethereumjs_util_1.hashPersonalMessage(message);
    const sig = ethereumjs_util_1.ecsign(msgHash, privateKey);
    const serialized = utils_1.concatSig(ethereumjs_util_1.toBuffer(sig.v), sig.r, sig.s);
    return serialized;
}
exports.personalSign = personalSign;
    "#;

    let s = hightlight(content, "js");
    println!("{}", s);
}

#[test]
fn highlight_all_theme() {
    let code = r#"
#[test]
fn regex_test() {
    let rex = Regex::new(r"^[^.]*\.(?P<suffix>[^.:]*):.*$").unwrap();
    if let Some(cap) =
        rex.captures("/home/x/code/code-rig/assets/test_src/AssetShareServiceImpl.java:11")
    {
        assert!(&cap["suffix"] == "java");
    }
}"#;
    let theme_set = ThemeSet::load_defaults();
    for (name, theme) in theme_set.themes {
        println!("theme name: {name}");
        let syntex_set = SyntaxSet::load_defaults_newlines();
        let language_syntax = syntex_set.find_syntax_by_extension("rs").unwrap();
        let mut highlight_lines = HighlightLines::new(language_syntax, &theme);
        let result: String = LinesWithEndings::from(code)
            .into_iter()
            .map(|line| {
                let ranges: Vec<(Style, &str)> =
                    highlight_lines.highlight_line(line, &syntex_set).unwrap();
                let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
                return escaped;
            })
            .collect();
        println!("{result}")
    }
}
